function RDualList(candidatesData, selectedData) {
	var table=document.createElement("table");
	this.ui=table;
	this.ui.model=this;
	table.className="RDualListTable";
	table.visibility="hidden";
	var tbody=document.createElement("tbody");
	table.insertBefore(tbody);
	var row=tbody.insertRow();
	var td1 = row.insertCell();
	td1.vAlign="top";
	var div1 = document.createElement("div");
	this.candidatesUI=div1;
	td1.insertBefore(div1);
	div1.noWrap=true;
	div1.className="RDualListContent";
	var td2 = row.insertCell();
	td2.vAlign="middle";
	td2.align="center";
	td2.width="40px";
	var addAllButton=document.createElement("button");
	td2.insertBefore(addAllButton);
	with (addAllButton) {
		addAllButton.model=this;
		value=">>";
		style.width="40px";
	}
	addAllButton.onclick=this.addAll;
	var addSelectedButton=document.createElement("button");
	td2.insertBefore(addSelectedButton);
	with (addSelectedButton) {
		addSelectedButton.model=this;
		value=">";
		style.width="40px";
	}
	addSelectedButton.onclick=this.addSelected;
	var removeSelectedButton=document.createElement("button");
	td2.insertBefore(removeSelectedButton);
	with (removeSelectedButton) {
	  removeSelectedButton.model=this;
		value="<<";
		style.width="40px";
	}
	removeSelectedButton.onclick=this.removeSelected;
	var removeAllButton=document.createElement("button");
	td2.insertBefore(removeAllButton);
	with (removeAllButton) {
		removeAllButton.model=this;
		value="<<<";
		style.width="40px";
	}
	removeAllButton.onclick=this.removeAll;
	var td3 = row.insertCell();
	td3.vAlign="top";
	var div3 = document.createElement("div");
	this.selectedUI=div3;
	td3.insertBefore(div3);
	div3.noWrap=true;
	div3.className="RDualListContent";
	this.setData(this.candidatesUI, candidatesData);
	this.setData(this.selectedUI, selectedData);
}
// class RDualListData{String caption; String value;}
RDualList.prototype={
	// public
	setCandidates: function(data) {
		// RDualListData[] data
		this.setData(this.candidatesUI, data);
	},
	// public
	setSelected: function(data) {
		// RDualListData[] data
		this.setData(this.selectedUI, data);
	},
	// private
	setData: function(which, data) {
		// DOM which
		// RDualListData[] data
		for (var i=0; i<data.length; ++i) {
			var span=document.createElement("span");
			which.insertBefore(span);
			span.innerHTML="<input type=checkbox>"+data[i].caption+"<br>";
			span.value=isDefined(data[i].value)?data[i].value:null;
		}
	},
	// public
	getCandidated: function() {return this.get(this.candidatesUI);},
	// public
	getSelected: function() { return this.get(this.selectedUI); },
	// private
	getData: function(which) {
		// return: RDualListData[]
		alert("not impl");
	},
	// public
	show: function(x, y, width, height) {
		this.setSize(width, height);
		with (this.ui.style) {
			position="absolute";
			left=x;
			top=y;
			visibility="visible";
		}
		document.body.insertBefore(this.ui);
	},
	// public
	showIn: function(holder, width, height) {
		this.setSize(width, height);
		this.ui.style.visibility="visible";
		document.getElementById(holder).appendChild(this.ui);
	},
	// private
	setSize: function(width, height) {
		this.ui.width=width;
		this.ui.height=height;
		var row=this.ui.children[0].rows[0];
		row.cells[0].width=(width-40)/2;
		row.cells[2].width=(width-40)/2;
	},	
	// private
	addAll: function() {
		// this refers to the button
		this.model.moveAll(this.model.candidatesUI, this.model.selectedUI);
	},
	// private
	removeAll: function () {
		// this refers to the button
		this.model.moveAll(this.model.selectedUI, this.model.candidatesUI);
	},
	// private
	addSelected: function() {
		// this refers to the button
		this.model.moveSelected(this.model.candidatesUI, this.model.selectedUI);
	},
	// private
	removeSelected: function() {
		// this refers to the button
		this.model.moveSelected(this.model.selectedUI, this.model.candidatesUI);
	},
	// private
	moveAll: function(source, target) {
		// source, target are div's
		while (source.children.length > 0){
			target.insertBefore(source.children[0]);
		}
	},
	// private
	moveSelected: function(source, target) {
		// source, target are div's
		var i = 0;
		while (i < source.children.length){
			if (source.children[i].children[0].checked)
				target.insertBefore(source.children[i]);
			else ++i;
		}
	}
}
